package com.huiying.cameramjpeg;

import android.text.TextUtils;
import android.util.Log;
import android.view.Surface;

import com.fvision.camera.iface.ICoreClientCallback;
import com.fvision.camera.manager.CameraStateIml;
import com.fvision.camera.manager.DevFileNameManager;
import com.fvision.camera.util.Cmd_Const;
import com.fvision.camera.util.FileUtils;
import com.fvision.camera.util.LogUtils;
import com.serenegiant.usb.IFrameCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * Created by admin on 2017/5/13.
 */

public class UvcCamera {
    static {
        System.loadLibrary("uvccamera-lib");
    }

    private LogListener mLogListener;
    private static volatile UvcCamera _instance;
    private int nativeFd = 0;
    public String fd_error = "";
    public String cmd_fd_error = "";
    private boolean isPx3 = false;

    public String getDevpath() {
        if (devpath == null) {
            return "";
        }
        return devpath;
    }

    private String devpath = "";
    private String serachDevpath = null;//上一次正确查找的U盘所在目录
    private boolean isInit = false;
    private boolean isPreviewing = false;
    private static IFrameCallback mFrameCallback;
    private static IFrameCallback mStateFrameCallback;
    private ICoreClientCallback mICoreClientCallback;
    private String pkgName = "";
    private byte[] buffer;
    private SearchUSB searchUsb = null;
    long lastStartPreviewTime = 0;
    long lastInit = 0;
    private List<ICoreClientCallback> listListener;

    public static UvcCamera getInstance() {
        if (_instance == null) {
            synchronized (UvcCamera.class) {
                if (_instance == null) {
                    _instance = new UvcCamera();
                    _instance.setStateFrameCallback(CameraStateIml.getInstance().mStateFrameCallback);
                }
            }
        }
        return _instance;
    }

    private UvcCamera() {
//        buffer = new byte[1280 * 720 * 4];
    }

    public void setOnCoreClientCallback(ICoreClientCallback callback) {
        mICoreClientCallback = callback;
    }
//    public synchronized void initUvccamera() {
//        if(isInit){
//            return;
//        }
//        if(searchUsb == null){
//            searchUsb = new SearchUSB();
//            searchUsb.setOnLog(mLogListener);
//        }
//
//        if(!TextUtils.isEmpty(devpath)){
//            File file = new File(devpath);
//            if(!file.exists()){
//                devpath = null;
//            }
//        }
//
//        if(TextUtils.isEmpty(devpath)){
//            devpath = searchUsb.searchUsbPath();
//        }
//
//        if(TextUtils.isEmpty(devpath)){
//            return;
//        }
//        Log.e("zoulequan"," UvcCamera init path "+ devpath);
////        String filename = String.format("Android/data/%s/VSFILE", pkgName);
////        String path = devpath.replace("VSFILE", filename);
//        String[] reault = initUvcCamera(getDevpath()).split("_");
//        fd_error = reault[1];
//        nativeFd = Integer.valueOf(reault[0]);
////        nativeFd = initUvcCamera(devpath);
//
//        Log.d("zoulequan", "UvcCamera isInit = "+(nativeFd > 0)+" devpath "+devpath);
//        if (nativeFd > 0) {
//            isInit = true;
//            fd_error = "Success";
//            initCmd();
////            initFile();
//        }
////        if(logfos!=null){
////            try {
////                logfos.write(("rootpath="+rootpath+"\n").getBytes());
////                logfos.flush();
////                logfos.close();
////            } catch (IOException e) {
////                e.printStackTrace();
////            }
////        }
//    }

    public void setOnLog(LogListener listener) {
        mLogListener = listener;
    }

//    public void initUvccamera(String path) {
//        if(isInit){
//            return;
//        }
//        if(searchUsb == null){
//            searchUsb = new SearchUSB();
//            searchUsb.setOnLog(mLogListener);
//        }
//        devpath = searchUsb.getFilePath(path);
//        String[] reault = initUvcCamera(getDevpath()).split("_");
//        fd_error = reault[1];
//        nativeFd = Integer.valueOf(reault[0]);
////        nativeFd = initUvcCamera(path);
//        Log.d("zoulequan", "UvcCamera isInit = "+(nativeFd > 0)+" devpath "+path);
//        Log.e("uvccmaera", path);
//        if (nativeFd > 0) {
//            isInit = true;
//            initCmd();
// //           initFile();
//        }
//    }

    public synchronized void initUvccamera() {
        long now = System.currentTimeMillis();
        if (now - lastInit < 1000 * 1) {
            LogUtils.d("runningLog","1秒内，过滤");
            return;
        }
        lastInit = now;
        ICoreClientCallback back;
        Iterator file1;
        if (isInit) {
            if (this.listListener != null) {
                file1 = this.listListener.iterator();
                while (file1.hasNext()) {
                    back = (ICoreClientCallback) file1.next();
                    back.onInit(false, 4, "已经初始化");
                    LogUtils.e("runningLog","已经初始化");
                }
            }
        }
        if (searchUsb == null) {
            searchUsb = new SearchUSB();
        }

        if (!TextUtils.isEmpty(devpath)) {
            File file = new File(devpath);
            if (!file.exists()) {
                devpath = null;
            }
        }

        if (TextUtils.isEmpty(devpath) && serachDevpath != null) {
            devpath = searchUsb.searchDir(serachDevpath);
            LogUtils.d("runningLog","上一次正确查找的U盘所在目录 "+devpath);
        }

        if (TextUtils.isEmpty(devpath)) {
            devpath = searchUsb.searchUsbPath();
        }

        if (TextUtils.isEmpty(devpath)) {
            fd_error = "not found file";
            LogUtils.e("runningLog","没有搜索到记录仪 not found file");
            return;
        }

        initUvccameraByPath(devpath);
    }

    //    public synchronized void initUvccameraByPath(String path) {
//        if (isInit) {
//            return;
//        }
//
//        File file = new File(path);
//        if (!file.exists()) {
//            return;
//        }
//
//        if (searchUsb == null) {
//            searchUsb = new SearchUSB();
//        }
//
//        if (file.isDirectory()) {
//            devpath = searchUsb.searchDir(path);
//        }
//
//        if (devpath == null) {
//            fd_error = "not found file!";
//            return;
//        }
//        String[] reault = initUvcCamera(devpath).split("_");
//        fd_error = reault[1];
//        nativeFd = Integer.valueOf(reault[0]);
////        nativeFd = initUvcCamera(devpath);
//
//        if (nativeFd > 0) {
//            isInit = true;
//            fd_error = "Success";
//            if (mICoreClientCallback != null) {
//                mICoreClientCallback.onIsAvailable(true);
//                mICoreClientCallback.onConnect();
//            }
//            initCmd();
//            // initFile();
//        }
//    }
    public synchronized void initUvccameraByPath(String path) {
        //     Log.d("zoulequan"," initUvccameraByPath "+isInit() + " "+path);
        if (isInit) {
            LogUtils.e("runningLog","已经初始化");
            return;
        }
        File file = new File(path);
        if (!file.exists()) {
            LogUtils.e("runningLog","路径不存在 "+path);
            return;
        }

        if (searchUsb == null) {
            searchUsb = new SearchUSB();
        }

        if (file.isDirectory()) {
            devpath = searchUsb.searchDir(path);
        }

        if (devpath == null) {
//            RunningLogManager.getInstance().recordLog("fd_error not:found file!");
            fd_error = "not found file!";
            LogUtils.e("runningLog","not found file!");
            return;
        }
        String[] reault = initUvcCamera(devpath).split("_");
        fd_error = reault[1];
        nativeFd = Integer.valueOf(reault[0]);
//        nativeFd = initUvcCamera(devpath);

        if (nativeFd > 0) {
            isInit = true;
            LogUtils.d("runningLog","预览初始化成功");
            fd_error = "Success";
            if (listListener != null) {

                for (ICoreClientCallback back : listListener) {
                    LogUtils.e("runningLog","回调 " + back.toString());
                    back.initCmd(true, fd_error);
                    back.onIsAvailable(true);
                    back.onConnect();
                }
            }else {
                LogUtils.e("runningLog","listListener == null");
            }
            initCmd();
            // initFile();
        } else {
            LogUtils.e("runningLog","预览初始化失败");
            //           RunningLogManager.getInstance().recordLog("预览初始化失败 "+fd_error);
            isInit = false;
            if (listListener != null) {
                for (ICoreClientCallback back : listListener) {
                    back.initCmd(false, fd_error);
                }
            }
        }
    }


    public int sendCmd(int requesttype, int request, int value, int index, int length, byte[] data) {
        if (nativeCmdFd > 0) {
            //Log.d("UvcCamera", "requesttype " + requesttype + " request " + request);
            return nativeSendCmd(nativeCmdFd, requesttype, request, value, index, length, data);
        } else {
//            if (nativeFd > 0) {
//                initCmd();
//            }
            Log.e("zoulequan", "nativeCmdFd <= 0 nativeCmdFd = " + nativeCmdFd);
        }
        return -1;
    }

    public int getFile(byte[] data) {
        if (nativeCmdFd > 0) {
            //return nativeGetFile(nativeFileFd, data);
            return nativeGetFile(nativeCmdFd, data, data.length);
        }
        return -1;
    }

    public int getFileCount(byte[] data) {
        if (nativeFileFd > 0) {
            return nativeGetFileCount(nativeFileFd, data);
        }
        return -1;
    }

    public synchronized void startPreview() {
//        if ((System.currentTimeMillis() - lastStartPreviewTime) < 1000) {//过滤避免频繁启动
//            return;
//        }
//        lastStartPreviewTime = System.currentTimeMillis();
//        if (isPreviewing) {
//            return;
//        }
//        if (isInit == false) {
//            isPreviewing = false;
//            return;
//        }
//        int ret = startPreview(nativeFd);
//        if (ret >= 0) {
//            isPreviewing = true;
//        }
        if ((System.currentTimeMillis() - lastStartPreviewTime) < 1000) {//过滤避免频繁启动
            return;
        }
        lastStartPreviewTime = System.currentTimeMillis();
        Log.e("startPreview", "开始预览");
        new Thread(new Runnable() {
            @Override
            public void run() {
                stopPreview();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                startPreviewOp();
            }
        }).start();

    }

    private void startPreviewOp() {
        int ret = startPreview(nativeFd);
        if (ret >= 0) {
            isPreviewing = true;
        }
    }

    public void stopPreview() {
        if (isInit == false) {
            isPreviewing = false;
            return;
        }
        if (nativeFd > 0) {
            stopPreview(nativeFd);
            isPreviewing = false;
        }
    }

    public void releaseUvccamera() {
        if (!isInit) {
            return;
        }
        if (mICoreClientCallback != null) {
            mICoreClientCallback.onDisconnect();
        }
        releaseUvcCamera(nativeFd);
//        releaseUvcCamera(nativeCmdFd);
        _instance = null;
        isInit = false;
        devpath = null;
        nativeFd = -1;
        nativeCmdFd = -1;
    }

    public void setFrameCallback(IFrameCallback frameCallback) {
        mFrameCallback = frameCallback;
        nativeFrameCallback(frameCallback);
    }


    public void setStateFrameCallback(IFrameCallback frameCallback) {
        mStateFrameCallback = frameCallback;
        nativeStateFrameCallback(frameCallback);
    }

    private native void nativeFrameCallback(IFrameCallback callback);

    private native void nativeStateFrameCallback(IFrameCallback callback);


    public native void setDisplaySurface(Surface surface);

    private native String initUvcCamera(String devpath);

    private native int startPreview(int fd);

    private native int stopPreview(int fd);

    private native int releaseUvcCamera(int fd);

    private native int nativeSendCmd(int fd, int requesttype, int request, int value, int index, int length, byte[] data);

    private native int nativeGetFile(int fd, byte[] data, int len);

    private native int nativeGetFileCount(int fd, byte[] data);

    public native void initGles(int width, int height);

    public native void changeESLayout(int width, int height);

    public native int drawESFrame();

    private native void nativeSetFrameCallback(int fd, IFrameCallback frameCallback);

    private native void nativeAdasFrameCallback(IFrameCallback callback);

    private native void nativeStartAdas(byte[] buffer);

    private native void nativeSetMainRuning(boolean run);

    private native boolean nativeTakesnoshot(String path);

    public native int getLanePara(int is_right, byte[] params);

    public native int setLanePara(int is_right, int start_x, int start_y,
                                  float slope, int w, int h, int threshold,
                                  int thresholdU, int thresholdV);

    public native int getLanePos(byte[] params);

    public native int setLanePos(int start_x, int start_y);

    public native boolean GetUploadAdasDataStatus();

    public native void SetUploadAdasDataStatus(boolean enable);

    public native boolean GetLibDispStatus();

    public native void SetLibDispStatus(boolean enable);	

    public native int GetStatus();

    private native boolean nativeDownloadFile(String downpath, String localpath, ProgressCallback callback);

    public static void onFrameData(byte[] data) {
        if (data != null) {
            if (mFrameCallback != null) {
                mFrameCallback.onFrame(data);
            }
//            Log.e("UvcCamera", String.format("data=%x,%x,%x,%x,%x,%x,%x,%x",data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]));
        }
    }

    public boolean isInit() {
        return isInit;
    }

    public void setAdasFrameCallback(IFrameCallback frameCallback) {
        if (frameCallback != null)
            nativeAdasFrameCallback(frameCallback);
    }

    public void setMainRuning(boolean run) {
        nativeSetMainRuning(run);
    }

    public boolean isPreviewing() {
        return isPreviewing;
    }

    public void setPkgName(String pkgName) {
        this.pkgName = pkgName;
    }

    public boolean takeSnapshot(String path) {
        if (TextUtils.isEmpty(path)) {
            return false;
        }
        return nativeTakesnoshot(path);
    }

    public boolean downloadFile(String downpath, String localpath, ProgressCallback callback) {
        return nativeDownloadFile(downpath, localpath, callback);
    }

    private String cmdpath = "";
    private int nativeCmdFd = 0;
    private boolean isCmdInit = false;

    public void setDevpath(String path) {
        devpath = path;
    }

    public void setSerachDevpath(String path) {
        serachDevpath = path;
    }

    public void initCmd() {
        LogUtils.d("runningLog","开始初始化指令文件");
        if (devpath == null) {
            cmd_fd_error = "devpath == null";
            LogUtils.e("runningLog","devpath == null");
            return;
        }

        if (DevFileNameManager.getInstance().getCurrentDev() == null ||
                TextUtils.isEmpty(DevFileNameManager.getInstance().getCurrentDev().getCmd())) {
            LogUtils.e("runningLog","DevFileNameManager == null");
            return;
        }
//        cmdpath = devpath.substring(0, devpath.lastIndexOf("/"));
//        cmdpath = String.format("%s/HWC", cmdpath, pkgName);//devpath.replace("fvfile","fvcfile");
//        if (!file.exists()) {

        String filename = String.format("Android/data/%s/" + DevFileNameManager.getInstance().getCurrentDev().getCmd(),
                DevFileNameManager.getInstance().getCurrentDev().getPackageName());

        //Log.e("initCmd", "" + filename + "getPreView" + DevFileNameManager.getInstance().getCurrentDev().getPreView() + "getCmd" + DevFileNameManager.getInstance().getCurrentDev().getCmd() + "getPackageName" + DevFileNameManager.getInstance().getCurrentDev().getPackageName());
//        cmdpath = devpath.replace("VSFILE", "HWC");
        cmdpath = devpath.replace(DevFileNameManager.getInstance().getCurrentDev().getPreView(), filename);
        LogUtils.d("runningLog","指令文件路径 "+cmdpath);
        // Log.e("zoulequan", "cmdpath = " + cmdpath);
        File file = new File(cmdpath);

//        nativeCmdFd = initUvcCmd(cmdpath);

//        String[] reault = initUvcCmd(cmdpath.replace("/storage", "/mnt/media_rw")).split("_");//px3 change
//        String[] reault = initUvcCmd(cmdpath).split("_");
        String[] reault;
        if (isPx3) {
            reault = initUvcCmd(cmdpath.replace("/storage", "/mnt/media_rw")).split("_");//px3 change
        } else {
            reault = initUvcCmd(cmdpath).split("_");
        }
        LogUtils.d("runningLog","reault[1] " + reault[1]);
        cmd_fd_error = cmdpath + " " + reault[1];
        nativeCmdFd = Integer.valueOf(reault[0]);
        //Log.d("zoulequan", " isCmdInit " + (nativeCmdFd > 0));
        if (nativeCmdFd > 0) {
            isCmdInit = true;
            cmd_fd_error = "Success";
            LogUtils.d("runningLog","初始化指令文件成功");
            if (listListener != null) {
                for (ICoreClientCallback back : listListener) {
                    LogUtils.d("runningLog","回调 "+back.getClass());
                    back.initCmd(true, cmd_fd_error);
                }
            }else {
                LogUtils.e("runningLog","无法回调 listListener==null");
            }
        } else {
            LogUtils.d("runningLog","初始化指令文件失败 "+cmd_fd_error);
            if (listListener != null) {
                for (ICoreClientCallback back : listListener) {
                    back.initCmd(false, cmd_fd_error);
                }
            }
            //Log.e("zoulequan", "initCmd fail cmdpath = " + cmdpath);
        }
//        if (mICoreClientCallback != null) {
//            mICoreClientCallback.initCmd(isCmdInit, cmd_fd_error);
//        }
        //Log.e("9527", "isCmdInit = " + isCmdInit);
    }

    private native String initUvcCmd(String devpath);


    private String filepath = "";
    private int nativeFileFd = 0;
    private boolean isFileInit = false;


    private native int initUvcFile(String devpath);

    private native int setPx3(boolean isPx3);

    public void setPx3Model(boolean isn) {
        isPx3 = isn;
        setPx3(isn);
    }

    public void addListener(ICoreClientCallback iCoreClientCallback) {
        if (iCoreClientCallback != null) {
            if (this.listListener == null) {
                this.listListener = new ArrayList();
            }

            if (this.listListener.size() > 0) {
                Iterator var2 = this.listListener.iterator();

                while (var2.hasNext()) {
                    ICoreClientCallback back = (ICoreClientCallback) var2.next();
                    if (back.getClass().equals(iCoreClientCallback.getClass())) {
                        this.listListener.remove(back);
                        break;
                    }
                }
            }

            this.listListener.add(iCoreClientCallback);
        }
    }

    /**
     * 获取视频时长指令 单独
     *
     * @param requesttype
     * @param request
     * @param value
     * @param index
     * @param fileName
     * @return
     */
//    public int sendCmd(int requesttype, int request, int value, int index, String fileName) {
//        if (nativeCmdFd > 0) {
//            Log.d("UvcCamera", "requesttype " + requesttype + " request " + request);
//            return nativeSendCmd(nativeCmdFd, requesttype, request, value, index, fileName);
//        } else {
//            if (nativeFd > 0) {
//                initCmd();
//            }
//            Log.e("zoulequan", "nativeCmdFd <= 0 nativeCmdFd = " + nativeCmdFd);
//        }
//        return -1;
//    }
}
